package org.chargecar.algodev;

import java.io.File;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.chargecar.algodev.knn.KnnTableTrainer;
import org.chargecar.prize.util.GPXTripParser;
import org.chargecar.prize.util.PointFeatures;
import org.chargecar.prize.util.Trip;
import org.chargecar.prize.util.TripFeatures;
import org.chargecar.prize.util.Vehicle;

/**
 * DO NOT EDIT Runs the simulation of an electric car running over a commute
 * defined by GPX file from real world commutes. Uses a compound energy storage
 * Policy to decide whether to get/store power in either the capacitor or
 * battery inside the car.
 * 
 * Competitors need only modify UserPolicy with their algorithm.
 * 
 * @author Alex Styler
 * 
 */
public class DumpData {
	static Vehicle civic = new Vehicle(1200, 1.988, 0.31, 0.015);
	static String currentDriver;
	static String directory;

	/**
	 * @param args
	 *            A pathname to a GPX file or folder containing GPX files (will
	 *            be recursively traversed) Alternate policies to test, either
	 *            in a referenced JAR file or within the project e.g. java
	 *            Simulator "C:\testdata\may" org.chargecar.policies.SpeedPolicy
	 *            java Simulator "C:\testdata" NaiveBufferPolicy SpeedPolicy
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		if (args == null) {
			System.err.println("ERROR: No GPX directory path provided.");
			System.exit(1);
		}

		String gpxFolder = args[0];
		String knnFolder = args[1];
		
		File folder = new File(gpxFolder);
		List<File> gpxFilesT = getGPXFiles(folder);
		List<File> gpxFiles = new ArrayList<File>(gpxFilesT.size());
		for (int i = gpxFilesT.size() - 1; i >= 0; i--) {
			gpxFiles.add(gpxFilesT.get(i));
		}

		System.out.println("Training on " + gpxFiles.size() + " GPX files.");
		KnnTableTrainer policy = new KnnTableTrainer(knnFolder);

		int count = 0;
		for (File tripFile : gpxFiles) {
			List<Trip> tripsToTest = parseTrips(tripFile);
			for (Trip t : tripsToTest) {
				try {
					policy.parseTrip(t);
					//policy.printPowerFlow();
					dumpData(t);
				} catch (IOException e) {
					System.out.print("Exception");
				}
				count++;
			}
		}
		policy.finishTraining();
		System.out.println("Complete. Trips trained on: " + count);
	}

	private static void dumpData(Trip trip) throws IOException {
		String driver = trip.getFeatures().getDriver();
		if (currentDriver == null || driver.compareTo(currentDriver) != 0) {
			currentDriver = driver;
			directory = "/Users/mac/Documents/workspace/dumpedData/"
					+ currentDriver;
			File file = new File(directory);
			boolean exist = file.exists();
			if (!exist) {
				System.out.println(directory);
				file.mkdirs();
			}
		}
		String tripName = trip.getFeatures().getFileName();
		System.out.println(tripName);
		FileWriter outfile = new FileWriter(directory + "/" + tripName);
		BufferedWriter out = new BufferedWriter(outfile);
		for (PointFeatures point : trip.getPoints()) {

			StringBuilder sb = new StringBuilder();

			sb.append(Double.toString(point.getLatitude()));
			sb.append(" ");
			sb.append(Double.toString(point.getLongitude()));
			sb.append(" ");
			sb.append(Double.toString(point.getElevation()));
			sb.append(" ");
			sb.append(Double.toString(point.getBearing()));
			sb.append(" ");
			sb.append(Double.toString(point.getPlanarDist()));
			sb.append(" ");
			sb.append(Double.toString(point.getAcceleration()));
			sb.append(" ");
			sb.append(Double.toString(point.getSpeed()));
			sb.append(" ");
			sb.append(Double.toString(point.getPeriodMS()));
			sb.append(" ");
			sb.append(Double
					.toString(point.getTime().get(Calendar.DAY_OF_WEEK)));
			sb.append(" ");
			sb.append(Integer.toString(point.getTime().get(Calendar.SECOND)
					+ point.getTime().get(Calendar.MINUTE) * 60
					+ point.getTime().get(Calendar.HOUR_OF_DAY) * 3600) );
			sb.append(" ");
			sb.append(Double.toString(point.getTotalPowerUsed()));
			sb.append(" ");
			sb.append(Double.toString(point.getPowerFlow()));
			String featureString = sb.toString();
			out.write(featureString);
			out.newLine();
		}

		out.close();
	}

	private static List<Trip> parseTrips(File gpxFile) throws IOException {
		List<Trip> trips = new ArrayList<Trip>();
		int i = 0;
		GPXTripParser gpxparser = new GPXTripParser();
		for (List<PointFeatures> tripPoints : gpxparser.read(gpxFile, civic, 240)) {
			String driverName = gpxFile.getParentFile().getName();
			String fileName = driverName
					+ gpxFile.getName().substring(0,
							gpxFile.getName().lastIndexOf('.')) + "_" + i;
			TripFeatures tf = new TripFeatures(driverName, fileName, civic,
					tripPoints.get(0));
			trips.add(new Trip(tf, tripPoints));
			gpxparser.clear();
			i++;
		}
		return trips;
	}

	static List<File> getGPXFiles(File gpxFolder) {
		List<File> gpxFiles = new ArrayList<File>();
		File[] files = gpxFolder.listFiles();
		for (File f : files) {
			if (f.isDirectory()) {
				gpxFiles.addAll(getGPXFiles(f));
			} else if (f.isFile()
					&& (f.getAbsolutePath().endsWith("gpx") || f
							.getAbsolutePath().endsWith("GPX"))) {
				gpxFiles.add(f);
			}
		}
		return gpxFiles;
	}
}
